using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 模板应用服务实现
    /// 提供模板管理的完整业务功能，包括模板的创建、查询、更新、删除等操作
    /// </summary>
    /// <remarks>
    /// 该服务负责处理模板相关的所有业务操作：
    /// - 模板的CRUD操作（创建、查询、更新、删除）
    /// - 分页查询和条件筛选
    /// - 按类型和分类的模板检索
    /// - 模板内容的验证和处理
    /// - 模板权限控制和状态管理
    /// </remarks>
    public class TemplateAppService : ITemplateAppService
    {
        private readonly ITemplateRepository _templateRepository;
        private readonly ILogger<TemplateAppService> _logger;

        /// <summary>
        /// 初始化模板应用服务
        /// </summary>
        /// <param name="templateRepository">模板数据仓储接口</param>
        /// <param name="logger">日志记录器</param>
        /// <exception cref="ArgumentNullException">当任何参数为null时抛出</exception>
        public TemplateAppService(
            ITemplateRepository templateRepository,
            ILogger<TemplateAppService> logger)
        {
            _templateRepository = templateRepository ?? throw new ArgumentNullException(nameof(templateRepository));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 获取分页的模板列表
        /// </summary>
        /// <param name="query">分页查询参数</param>
        /// <returns>分页的模板数据</returns>
        /// <exception cref="ArgumentNullException">query为null时抛出</exception>
        /// <exception cref="Exception">数据库查询异常</exception>
        /// <remarks>
        /// 支持的查询条件：
        /// - 关键字搜索（模板名称）
        /// - 分页参数控制
        /// - 返回包含总数和分页信息的结果
        /// </remarks>
        public async Task<PagedResultDto<TemplateDto>> GetPagedListAsync(PagedQueryDto query)
        {
            if (query == null) throw new ArgumentNullException(nameof(query));

            try
            {
                _logger.LogInformation("获取分页模板列表，页码: {PageIndex}，页大小: {PageSize}，关键字: {Keyword}", 
                    query.PageIndex, query.PageSize, query.Keyword);

                var result = await _templateRepository.GetPagedAsync(
                    query.PageIndex, 
                    query.PageSize,
                    string.IsNullOrEmpty(query.Keyword) ? null : t => t.Name.Contains(query.Keyword));

                var templateDtos = result.Items.Select(MapToDto).ToList();

                var pagedResult = new PagedResultDto<TemplateDto>
                {
                    Items = templateDtos,
                    TotalCount = result.Total,
                    PageIndex = query.PageIndex,
                    PageSize = query.PageSize
                };

                _logger.LogInformation("成功获取分页模板列表，返回 {Count} 条记录，总计 {Total} 条", 
                    templateDtos.Count, result.Total);

                return pagedResult;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取分页模板列表失败");
                throw;
            }
        }

        /// <summary>
        /// 根据类型获取模板列表
        /// </summary>
        /// <param name="type">模板类型</param>
        /// <returns>指定类型的模板列表</returns>
        /// <exception cref="ArgumentException">type为空或null时抛出</exception>
        /// <exception cref="Exception">数据库查询异常</exception>
        /// <remarks>
        /// 支持的模板类型包括但不限于：
        /// - "page" - 页面模板
        /// - "component" - 组件模板
        /// - "form" - 表单模板
        /// - "layout" - 布局模板
        /// </remarks>
        public async Task<List<TemplateDto>> GetByTypeAsync(string type)
        {
            if (string.IsNullOrWhiteSpace(type)) 
                throw new ArgumentException("模板类型不能为空", nameof(type));

            try
            {
                _logger.LogInformation("根据类型获取模板列表: {Type}", type);

                var templates = await _templateRepository.GetByTypeAsync(type);
                var result = templates.Select(MapToDto).ToList();

                _logger.LogInformation("根据类型 {Type} 获取到 {Count} 个模板", type, result.Count);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据类型获取模板列表失败: {Type}", type);
                throw;
            }
        }

        /// <summary>
        /// 根据分类获取模板列表
        /// </summary>
        public async Task<List<TemplateDto>> GetByCategoryAsync(string category)
        {
            try
            {
                var templates = await _templateRepository.FindAsync(t => t.Type == category);
                return templates.Select(MapToDto).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据分类获取模板列表失败: {Category}", category);
                throw;
            }
        }

        /// <summary>
        /// 根据ID获取模板详情
        /// </summary>
        public async Task<TemplateDto?> GetByIdAsync(long id)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                return template == null ? null : MapToDto(template);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据ID获取模板失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 根据名称获取模板
        /// </summary>
        public async Task<TemplateDto?> GetByNameAsync(string name)
        {
            try
            {
                var template = await _templateRepository.FindSingleAsync(t => t.Name == name);
                return template == null ? null : MapToDto(template);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据名称获取模板失败: {Name}", name);
                throw;
            }
        }

        /// <summary>
        /// 创建模板
        /// </summary>
        public async Task<TemplateDto> CreateAsync(TemplateDto dto)
        {
            try
            {
                // 验证模板内容
                var validation = await ValidateAsync(dto.Content, dto.Engine ?? "razor");
                if (!validation.IsValid)
                {
                    throw new ArgumentException($"模板内容验证失败: {string.Join(", ", validation.Errors)}");
                }

                var template = new Template
                {
                    Name = dto.Name,
                    Type = dto.Type,
                    Content = dto.Content,
                    PreviewImage = dto.PreviewImage,
                    Version = 1, // 新模板版本从1开始
                    Status = 1, // 启用
                    CreatedBy = 1, // 这里需要从上下文获取当前用户ID
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                await _templateRepository.AddAsync(template);
                await _templateRepository.SaveChangesAsync();

                _logger.LogInformation("模板创建成功: {Name}", dto.Name);
                return MapToDto(template);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建模板失败: {Name}", dto.Name);
                throw;
            }
        }

        /// <summary>
        /// 更新模板
        /// </summary>
        public async Task<TemplateDto> UpdateAsync(long id, TemplateDto dto)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    throw new ArgumentException($"模板不存在: {id}");
                }

                // 验证模板内容
                var validation = await ValidateAsync(dto.Content, dto.Engine ?? "razor");
                if (!validation.IsValid)
                {
                    throw new ArgumentException($"模板内容验证失败: {string.Join(", ", validation.Errors)}");
                }

                template.Name = dto.Name;
                template.Type = dto.Type;
                template.Content = dto.Content;
                template.PreviewImage = dto.PreviewImage;
                template.Version += 1; // 更新时版本号递增
                template.UpdatedBy = 1; // 这里需要从上下文获取当前用户ID
                template.UpdatedAt = DateTime.UtcNow;

                await _templateRepository.SaveChangesAsync();

                _logger.LogInformation("模板更新成功: {Name}", dto.Name);
                return MapToDto(template);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新模板失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 删除模板
        /// </summary>
        public async Task<bool> DeleteAsync(long id)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    return false;
                }

                await _templateRepository.DeleteAsync(template);
                await _templateRepository.SaveChangesAsync();

                _logger.LogInformation("模板删除成功: {Id}", id);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除模板失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 批量删除模板
        /// </summary>
        public async Task<bool> BatchDeleteAsync(List<long> ids)
        {
            try
            {
                var templates = await _templateRepository.FindAsync(t => ids.Contains(t.Id));
                
                foreach (var template in templates)
                {
                    await _templateRepository.DeleteAsync(template);
                }

                await _templateRepository.SaveChangesAsync();

                _logger.LogInformation("批量删除模板成功: {Count}", templates.Count);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除模板失败");
                throw;
            }
        }

        /// <summary>
        /// 检查模板名称是否存在
        /// </summary>
        public async Task<bool> ExistsAsync(string name, long? excludeId = null)
        {
            try
            {
                return await _templateRepository.ExistsAsync(t => 
                    t.Name == name && (!excludeId.HasValue || t.Id != excludeId.Value));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查模板名称是否存在失败: {Name}", name);
                throw;
            }
        }

        /// <summary>
        /// 获取默认模板
        /// </summary>
        public async Task<TemplateDto?> GetDefaultAsync(string type)
        {
            try
            {
                var template = await _templateRepository.GetDefaultAsync(type);
                return template == null ? null : MapToDto(template);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取默认模板失败: {Type}", type);
                throw;
            }
        }

        /// <summary>
        /// 设置默认模板
        /// </summary>
        public async Task<bool> SetDefaultAsync(long id)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    return false;
                }

                // 取消同类型其他模板的默认状态
                var sameTypeTemplates = await _templateRepository.FindAsync(t => 
                    t.Type == template.Type && t.Id != id && t.Status == 1);

                foreach (var t in sameTypeTemplates)
                {
                    // 这里需要实体有IsDefault字段，目前简化处理
                    t.UpdatedAt = DateTime.UtcNow;
                }

                template.UpdatedAt = DateTime.UtcNow;
                await _templateRepository.SaveChangesAsync();

                _logger.LogInformation("设置默认模板成功: {Id}", id);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置默认模板失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 设置模板启用状态
        /// </summary>
        public async Task<bool> SetEnabledAsync(long id, bool enabled)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    return false;
                }

                template.Status = enabled ? (byte)1 : (byte)0;
                template.UpdatedAt = DateTime.UtcNow;
                await _templateRepository.SaveChangesAsync();

                _logger.LogInformation("设置模板状态成功: {Id}, Enabled: {Enabled}", id, enabled);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置模板状态失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 渲染模板
        /// </summary>
        public async Task<string> RenderAsync(long id, object data)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    throw new ArgumentException($"模板不存在: {id}");
                }

                // 增加使用次数
                await IncrementUsageCountAsync(id);

                return await RenderContentAsync(template.Content!, data, "razor"); // 默认使用 Razor 引擎
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "渲染模板失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 渲染模板内容
        /// </summary>
        public async Task<string> RenderContentAsync(string content, object data, string engine = "razor")
        {
            try
            {
                return engine.ToLower() switch
                {
                    "razor" => await RenderRazorAsync(content, data),
                    "liquid" => await RenderLiquidAsync(content, data),
                    "handlebars" => await RenderHandlebarsAsync(content, data),
                    _ => throw new NotSupportedException($"不支持的模板引擎: {engine}")
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "渲染模板内容失败");
                throw;
            }
        }

        /// <summary>
        /// 预览模板
        /// </summary>
        public async Task<string> PreviewAsync(long id, object? data = null)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    throw new ArgumentException($"模板不存在: {id}");
                }

                // 使用默认数据或提供的数据进行预览
                var previewData = data ?? GetDefaultPreviewData();
                
                return await RenderContentAsync(template.Content!, previewData, "razor"); // 默认使用 Razor 引擎
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "预览模板失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 验证模板
        /// </summary>
        public async Task<(bool IsValid, string[] Errors)> ValidateAsync(string content, string engine = "razor")
        {
            try
            {
                var errors = new List<string>();

                if (string.IsNullOrEmpty(content))
                {
                    errors.Add("模板内容不能为空");
                }

                // 根据引擎类型进行语法验证
                switch (engine.ToLower())
                {
                    case "razor":
                        errors.AddRange(await ValidateRazorAsync(content));
                        break;
                    case "liquid":
                        errors.AddRange(await ValidateLiquidAsync(content));
                        break;
                    case "handlebars":
                        errors.AddRange(await ValidateHandlebarsAsync(content));
                        break;
                    default:
                        errors.Add($"不支持的模板引擎: {engine}");
                        break;
                }

                return (errors.Count == 0, errors.ToArray());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证模板失败");
                return (false, new[] { ex.Message });
            }
        }

        /// <summary>
        /// 复制模板
        /// </summary>
        public async Task<TemplateDto> CopyAsync(long id, string newName)
        {
            try
            {
                var originalTemplate = await _templateRepository.GetByIdAsync(id);
                if (originalTemplate == null)
                {
                    throw new ArgumentException($"模板不存在: {id}");
                }

                var newTemplate = new Template
                {
                    Name = newName,
                    Type = originalTemplate.Type,
                    Content = originalTemplate.Content,
                    PreviewImage = originalTemplate.PreviewImage,
                    Version = 1, // 新复制的模板版本从1开始
                    Status = originalTemplate.Status,
                    CreatedBy = 1, // 这里需要从上下文获取当前用户ID
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                await _templateRepository.AddAsync(newTemplate);
                await _templateRepository.SaveChangesAsync();

                _logger.LogInformation("复制模板成功: {OriginalId} -> {NewName}", id, newName);
                return MapToDto(newTemplate);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "复制模板失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 增加使用次数
        /// </summary>
        public async Task<bool> IncrementUsageCountAsync(long id)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    return false;
                }

                // 这里需要实体有UsageCount字段，目前简化处理
                template.UpdatedAt = DateTime.UtcNow;
                await _templateRepository.SaveChangesAsync();

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "增加使用次数失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 获取模板变量
        /// </summary>
        public async Task<Dictionary<string, object>> GetVariablesAsync(long id)
        {
            try
            {
                var template = await _templateRepository.GetByIdAsync(id);
                if (template == null)
                {
                    throw new ArgumentException($"模板不存在: {id}");
                }

                // 从模板内容中解析变量（简单实现）
                return ExtractVariablesFromContent(template.Content);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取模板变量失败: {Id}", id);
                throw;
            }
        }

        /// <summary>
        /// 导出模板
        /// </summary>
        public async Task<byte[]> ExportAsync(List<long> ids)
        {
            try
            {
                var templates = await _templateRepository.FindAsync(t => ids.Contains(t.Id));
                var templateDtos = templates.Select(MapToDto).ToList();

                var json = JsonSerializer.Serialize(templateDtos, new JsonSerializerOptions 
                { 
                    WriteIndented = true 
                });

                return System.Text.Encoding.UTF8.GetBytes(json);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导出模板失败");
                throw;
            }
        }

        /// <summary>
        /// 导入模板
        /// </summary>
        public async Task<List<TemplateDto>> ImportAsync(byte[] data)
        {
            try
            {
                var json = System.Text.Encoding.UTF8.GetString(data);
                var templateDtos = JsonSerializer.Deserialize<List<TemplateDto>>(json);

                if (templateDtos == null || !templateDtos.Any())
                {
                    throw new ArgumentException("导入数据为空或格式错误");
                }

                var result = new List<TemplateDto>();

                foreach (var dto in templateDtos)
                {
                    // 检查名称是否已存在
                    var existingName = dto.Name;
                    var counter = 1;
                    while (await ExistsAsync(existingName))
                    {
                        existingName = $"{dto.Name}_{counter}";
                        counter++;
                    }
                    
                    dto.Name = existingName;
                    var created = await CreateAsync(dto);
                    result.Add(created);
                }

                _logger.LogInformation("导入模板成功: {Count}", result.Count);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "导入模板失败");
                throw;
            }
        }

        #region Private Methods

        /// <summary>
        /// 将实体映射为DTO
        /// </summary>
        private static TemplateDto MapToDto(Template template)
        {
            return new TemplateDto
            {
                Id = template.Id,
                Name = template.Name,
                Type = template.Type,
                Content = template.Content ?? string.Empty,
                Variables = null, // 实体中没有Variables字段，设为null
                Engine = "razor", // 默认引擎
                Status = template.Status == 1 ? "Active" : "Inactive",
                Version = template.Version.ToString() ?? "1", // 修复：直接转换int到string
                PreviewImage = template.PreviewImage,
                IsEnabled = template.Status == 1,
                CreatedAt = template.CreatedAt,
                UpdatedAt = template.UpdatedAt
            };
        }

        /// <summary>
        /// Razor模板渲染 (简化实现)
        /// </summary>
        private async Task<string> RenderRazorAsync(string content, object data)
        {
            // 这里需要集成RazorEngine库，目前返回简化版本
            await Task.CompletedTask;
            
            // 简单的变量替换
            var result = content;
            if (data != null)
            {
                var properties = data.GetType().GetProperties();
                foreach (var prop in properties)
                {
                    var value = prop.GetValue(data)?.ToString() ?? string.Empty;
                    result = result.Replace($"@Model.{prop.Name}", value);
                }
            }
            
            return result;
        }

        /// <summary>
        /// Liquid模板渲染 (简化实现)
        /// </summary>
        private async Task<string> RenderLiquidAsync(string content, object data)
        {
            await Task.CompletedTask;
            // 这里需要集成Liquid.NET库
            return content; // 简化实现
        }

        /// <summary>
        /// Handlebars模板渲染 (简化实现)
        /// </summary>
        private async Task<string> RenderHandlebarsAsync(string content, object data)
        {
            await Task.CompletedTask;
            // 这里需要集成Handlebars.Net库
            return content; // 简化实现
        }

        /// <summary>
        /// Razor模板验证
        /// </summary>
        private async Task<List<string>> ValidateRazorAsync(string content)
        {
            await Task.CompletedTask;
            var errors = new List<string>();

            // 简单的语法检查
            if (content.Contains("@{") && !content.Contains("}"))
            {
                errors.Add("Razor语法错误：代码块未正确关闭");
            }

            return errors;
        }

        /// <summary>
        /// Liquid模板验证
        /// </summary>
        private async Task<List<string>> ValidateLiquidAsync(string content)
        {
            await Task.CompletedTask;
            var errors = new List<string>();

            // 检查Liquid标签是否配对
            var openTags = Regex.Matches(content, @"\{\%\s*(\w+)");
            var closeTags = Regex.Matches(content, @"\{\%\s*end(\w+)");

            if (openTags.Count != closeTags.Count)
            {
                errors.Add("Liquid标签未正确配对");
            }

            return errors;
        }

        /// <summary>
        /// Handlebars模板验证
        /// </summary>
        private async Task<List<string>> ValidateHandlebarsAsync(string content)
        {
            await Task.CompletedTask;
            var errors = new List<string>();

            // 检查Handlebars表达式是否配对
            var openCount = content.Count(c => c == '{');
            var closeCount = content.Count(c => c == '}');

            if (openCount != closeCount)
            {
                errors.Add("Handlebars表达式括号未配对");
            }

            return errors;
        }

        /// <summary>
        /// 获取默认预览数据
        /// </summary>
        private static object GetDefaultPreviewData()
        {
            return new { Title = "示例标题", Content = "示例内容", Date = DateTime.Now };
        }

        /// <summary>
        /// 从模板内容中提取变量
        /// </summary>
        private static Dictionary<string, object> ExtractVariablesFromContent(string? content)
        {
            var variables = new Dictionary<string, object>();
            
            if (string.IsNullOrEmpty(content))
                return variables;

            // 简单的变量提取逻辑 (提取 {{variable}} 格式的变量)
            var regex = new System.Text.RegularExpressions.Regex(@"\{\{(\w+)\}\}");
            var matches = regex.Matches(content);
            
            foreach (System.Text.RegularExpressions.Match match in matches)
            {
                var varName = match.Groups[1].Value;
                if (!variables.ContainsKey(varName))
                {
                    variables[varName] = $"示例{varName}";
                }
            }

            return variables;
        }

        #endregion
    }
}
